package com.liuya.db.orm.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.liuya.common.exception.EntityExistException;
import com.liuya.common.Util;
import com.liuya.db.ColumnAdapter;
import com.liuya.db.DBLevelException;
import com.liuya.db.DBPower;
import com.liuya.db.util.DBUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.liuya.db.orm.Column;
import com.liuya.db.orm.Table;
import com.liuya.db.orm.TableUpdator;

public class TableUpdatorImpl implements TableUpdator {

	private Table table;
	private String updateSql;
	private TableSelectorImpl selector;

	private static Log logger = LogFactory.getLog(TableUpdatorImpl.class);

	public Table getTable() {
		return table;
	}

	public void setTable(Table table) {
		this.table = table;

		if (!Util.isEmpty(table.getIdColumns())) {
			updateSql = DBUtil.updateSql(table.getName(), table.getIdColumnNames(), table.getExceptIdColumnNames());
		}

		selector = new TableSelectorImpl();
		selector.setTable(table);
	}

	public void updateByIdColumns(Object newValue) throws EntityExistException {
		Connection conn = null;
		try {
			conn = DBPower.getConnectionByTableId(table.getId());
			updateByIdColumns(conn, newValue);
		} finally {
			DBUtil.close(conn);
		}
	}

	public void updateByIdColumns(Connection conn, Object newValue) throws EntityExistException {
		PreparedStatement pstmt = null;
		try {
			pstmt = conn.prepareStatement(updateSql);
			// set UPDATE SET PART VALUES
			Column[] exceptIdColumns = table.getExceptIdColumns();
			for (int i = 0; i < exceptIdColumns.length; i++) {
				Column column = exceptIdColumns[i];
				ColumnAdapter columnAdapter = column.getAdapter();
				columnAdapter.setPreparedStatement(pstmt, i + 1, newValue);
			}

			// set UPDATE WHERE PART VALUES
			int offset = exceptIdColumns.length + 1;
			Column[] idColumns = table.getIdColumns();
			for (int i = 0; i < idColumns.length; i++) {
				Column column = idColumns[i];
				ColumnAdapter columnAdapter = column.getAdapter();
				columnAdapter.setPreparedStatement(pstmt, i + offset, newValue);
			}

			pstmt.executeUpdate();
		} catch (SQLException e) {
			logger.error("", e);

			if (conn != null) {
				// violate pk or unique constraints?
				if (!Util.isEmpty(table.getUniqueColumns())) {
					boolean isExist = selector.isExistByUniqueColumns(conn, newValue);
					if (isExist) {
						throw new EntityExistException(newValue);
					}
				}

				throw new DBLevelException(e);
			} else {
				throw new DBLevelException(e);
			}
		} finally {
			DBUtil.close(pstmt);
		}
	}
}
